#pragma once

#include <iostream>
#include <pthread.h>
#include <functional>
#include <string>
#include <cassert>
#include <memory>
#include <unistd.h>

class Thread;

class Context
{
public:
    Thread *_this;
    void *_args;

    Context()
    :_this(nullptr),_args(nullptr)
    {}

    ~Context()
    {}
};

class Thread
{
public:
    typedef std::function<void *(void *)> func_t;
    const int num = 1024;

public:
    Thread(func_t func, void *args, int number)
        : _func(func), _args(args)
    {
        char buf[num];
        snprintf(buf, sizeof(buf), "新线程-%d", number);
        _name = buf;

        Context *ctx = new Context;
        ctx->_this = this;
        ctx->_args = _args;
        int n = pthread_create(&_tid, nullptr, start_routine, ctx);
        assert(n == 0);
        (void)n;
    }

    // 线程函数要要求为    void*，void*(*)(void*)
    // void add()  add的类型为：void(*)()，add类型为函数指针
    // void *start_routine(void* args)，start_routine的类型void*(Thread::*)(void*)，这样多一个this指针，注意this指针的位置
    // void *start_routine(),  类型为void*(Thread::*)() ，也不符合，没有void*参数，且仍有this指针，
    // 可以认为，this指针实际是在函数指针类型前加了类类型和作用域限定符，即Thread::
    // 只能设置为静态的，因为静态成员函数没有this指针
    static void *start_routine(void *args)
    {
        //  _func(args);    // 没有this指针，无法访问非静态 成员

        Context *ctx = (Context *)args;
        ctx->_this->_func(ctx->_args);
    }

    void join()
    {
        int n=pthread_join(_tid,nullptr);
        assert(n==0);   //编译debug的方式发布时，assert语句存在，release方式发布就不存在了，n就成了定义但未使用，可能warning
        (void)n;    
    }

    ~Thread()
    {

    }

private:
    std::string _name;
    void *_args;
    pthread_t _tid;
    func_t _func;
};